namespace Maple.Branch.IdentityServer.Extensions
{
    using System.IdentityModel.Tokens.Jwt;
    using AspNetIdentity;
    using Identity.Entities;
    using IdentityModel;
    using IdentityServer4.Services;
    using IdentityServer4.Stores;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection.Extensions;
    using Options;
    using Services;
    using Volo.Abp.Security.Claims;

    public static class IdentityServerBuilderExtensions
    {
        public static IIdentityServerBuilder AddBranchStores(this IIdentityServerBuilder builder)
        {
            builder.Services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();

            builder.Services.AddTransient<IDeviceFlowStore, DeviceFlowStore>();

            return builder
                .AddClientStore<ClientStore>()
                .AddResourceStore<BranchResourceStore>()
                .AddCorsPolicyService<BranchCorsPolicyService>();
        }

        public static IIdentityServerBuilder AddBranchIdentityServer(
            this IIdentityServerBuilder builder,
            BranchIdentityServerBuilderOptions options = null)
        {
            if (options == null)
            {
                options = new BranchIdentityServerBuilderOptions();
            }

            //TODO: AspNet Identity integration lines. Can be extracted to a extension method
            if (options.IntegrateToAspNetIdentity)
            {
                builder.AddAspNetIdentity<IdentityUser>();
                builder.AddProfileService<BranchProfileService>();
                builder.AddResourceOwnerValidator<BranchResourceOwnerPasswordValidator>();
            }

            builder.Services.Replace(ServiceDescriptor.Transient<IClaimsService, BranchClaimsService>());

            if (options.UpdateAbpClaimTypes)
            {
                AbpClaimTypes.UserId = JwtClaimTypes.Subject;
                AbpClaimTypes.UserName = JwtClaimTypes.Name;
                AbpClaimTypes.Role = JwtClaimTypes.Role;
                AbpClaimTypes.Email = JwtClaimTypes.Email;
            }

            if (options.UpdateJwtSecurityTokenHandlerDefaultInboundClaimTypeMap)
            {
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.UserId] = AbpClaimTypes.UserId;
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.UserName] = AbpClaimTypes.UserName;
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.Role] = AbpClaimTypes.Role;
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.Email] = AbpClaimTypes.Email;
            }

            return builder;
        }
    }
}
